# coding: utf-8
from py2neo import Graph
import neotime
import query_backend.config as config


class AnswerSearch:
    def __init__(self):
        self.g = Graph(config.host, auth=(config.username, config.password))
        self.num_limit = 20

    '''构建实体字典'''

    def build_entitydict(self, args):
        entity_dict = {}
        for arg, types in args.items():
            for type in types:
                if type not in entity_dict:
                    entity_dict[type] = [arg]
                else:
                    entity_dict[type].append(arg)
        return entity_dict

    '''根据问题不同生成对应cql语句'''

    def answer_cql(self, res_classify):
        args = res_classify['args']
        entity_dict = self.build_entitydict(args)
        question_types = res_classify['question_types']
        cqls = []
        for question_type in question_types:
            cql_ = {'question_type': question_type}
            cql = []

            '''针对不同的问题，分开进行处理'''
            if question_type == 'movie_star' or question_type == 'movie_time' or question_type == 'movie_show_start':
                if not entity_dict.get('movie'):
                    continue
                cql = ["MATCH (m:Movie) where m.name='{0}' return m".format(i) for i in entity_dict.get('movie')]

            elif question_type == 'movie_toMovie':
                if not entity_dict.get('movie'):
                    continue
                cql = ["MATCH (m:Movie) where m.name=~'.*{0}.*' return m".format(i) for i in entity_dict.get('movie')]

            elif question_type == 'movie_actor':
                if not entity_dict.get('movie'):
                    continue
                cql = ["MATCH (m:Actor)-[r:`主演`]-(n:Movie) where n.name = '{0}' return m".format(i) for i in
                       entity_dict.get('movie')]

            elif question_type == 'movie_director':
                if not entity_dict.get('movie'):
                    continue
                cql = ["MATCH (m:Director)-[r:`导演`]-(n:Movie) where n.name = '{0}' return m".format(i) for i in
                       entity_dict.get('movie')]

            elif question_type == "movie_type":
                if not entity_dict.get('movie'):
                    continue
                cql = ["MATCH (m:Genre)-[r:`属于`]-(n:Movie) where n.name = '{0}' return m".format(i) for i in
                       entity_dict.get('movie')]

            elif question_type == 'type_movie':
                if not entity_dict.get('type'):
                    continue
                cql = ["MATCH (m:Movie)-[r:`属于`]->(n:Genre) where n.name = '{0}' return m".format(i) for i in
                       entity_dict.get('type')]

            elif question_type == 'actor_movie':
                if not entity_dict.get('actor'):
                    continue
                cql = ["MATCH (m:Movie)-[r:`主演`]-(n:Actor) where n.name =~'.*{0}.*' return m".format(i) for i in
                       entity_dict.get('actor')]

            elif question_type == 'director_movie':
                if not entity_dict.get('director'):
                    continue
                cql = ["MATCH (m:Movie)-[r:`导演`]-(n:Director) where n.name =~'.*{0}.*' return m".format(i) for i in
                       entity_dict.get('director')]

            elif question_type == 'associate_person':
                if not entity_dict.get('actor'):
                    continue
                cql = ["MATCH (m:Actor {name:'%s'})-[:`主演`]-(n:Movie)-[:`主演`]-(r) return m,r" % i for i in
                       entity_dict.get('actor')]

            elif question_type == 'associate_movie':
                if not entity_dict.get('actor'):
                    continue
                try:
                    List = []
                    for i in entity_dict.get('actor'):
                        List.append(i)
                    k = len(List)
                    m, n = List[0:k]
                    cql = ["MATCH (m:Actor {name:'%s'})-[:`主演`]-(n:Movie)-[:`主演`]-(r:Actor{name:'%s'}) return n" % (
                        m, n)]
                except:
                    print('不符合该模块的格式pass1过滤掉')
                    pass

            elif question_type == 'date_movie' or question_type == 'less_date_movie' or question_type == 'more_date_movie':
                if not entity_dict.get('date'):
                    continue
                List = []
                for i in entity_dict.get('date'):
                    if i.isdigit():
                        List.append(i)
                if question_type == 'date_movie':
                    cql = ["MATCH (m:Movie) where m.releaseTime = date('%s') return m" % i for i in
                           entity_dict.get('date')]
                elif question_type == 'less_date_movie':
                    cql = ["MATCH (m:Movie) where m.releaseTime < date('%s-01-01') return m" % i for i in
                           entity_dict.get('date')]
                elif question_type == 'more_date_movie':
                    cql = ["MATCH (m:Movie) where m.releaseTime > date('%s-01-01') return m" % i for i in
                           entity_dict.get('date')]

            elif question_type == 'range_movie_date':
                if not entity_dict.get('date'):
                    continue
                List = []
                for i in entity_dict.get('date'):
                    if i.isdigit():
                        List.append(i)
                k = len(List)
                m, n = List[0:k]
                cql = [
                    "MATCH (m:Movie) where m.releaseTime > date('%s-01-01') and m.releaseTime < date('%s-01-01') return m" % (
                    m, n)]

            elif question_type == 'time_movie' or question_type == 'less_time_movie' or question_type == 'more_time_movie':
                if not entity_dict.get('time'):
                    continue
                List = []
                for i in entity_dict.get('time'):
                    if i.isdigit():
                        List.append(i)
                if question_type == 'time_movie':
                    cql = ["match(movies:Movie) where movies.runTime = {0} return movies".format(j) for j in List]
                elif question_type == 'less_time_movie':
                    cql = ["match(movies:Movie) where movies.runTime < {0} return movies".format(j) for j in List]
                elif question_type == 'more_time_movie':
                    cql = ["match(movies:Movie) where movies.runTime > {0} return movies".format(j) for j in List]

            elif question_type == 'range_time_movie':
                if not entity_dict.get('time'):
                    continue
                try:
                    List = []
                    for i in entity_dict.get('time'):
                        if i.isdigit():
                            List.append(i)
                    k = len(List)
                    List.sort()
                    m, n = List[0:k]
                    cql = [
                        "match(movies:Movie) where movies.runTime > {0} and movies.runTime < {1} return movies".format(
                            m, n)]
                except:
                    print('不符合该模块的格式pass2过滤掉')
                    pass

            elif question_type == 'star_movie' or question_type == 'less_star_movie' or question_type == 'more_star_movie':
                if not entity_dict.get('star'):
                    continue
                List = []
                for i in entity_dict.get('star'):
                    try:
                        I = float(i)
                        List.append(I)
                    except:
                        pass
                if question_type == 'star_movie':
                    cql = ["match(movies:Movie) where movies.star = {0} return movies".format(j) for j in List]
                elif question_type == 'less_star_movie':
                    cql = ["match(movies:Movie) where movies.star < {0} return movies".format(j) for j in List]
                elif question_type == 'more_star_movie':
                    cql = ["match(movies:Movie) where movies.star > {0} return movies".format(j) for j in List]

            elif question_type == 'range_star_movie':
                if not entity_dict.get('star'):
                    continue
                try:
                    List = []
                    for i in entity_dict.get('star'):
                        try:
                            I = float(i)
                            List.append(I)
                        except:
                            pass
                    k = len(List)
                    List.sort()
                    m, n = List[0:k]
                    cql = [
                        "match(movies:Movie) where movies.star > {0} and movies.star < {1} return movies".format(m, n)]
                except:
                    print('不符合该模块的格式pass2过滤掉')
                    pass

            if cql:
                cql_['cql'] = cql
                cqls.append(cql_)

        if len(question_types) == 0:
            List = []
            for i in entity_dict.get('movie'):
                List.append(i)
            cql_ = {'question_type': '', 'cql': ["MATCH (m:Movie) where m.name =~ '.*%s.*' return m" % i for i in List]}
            cqls.append(cql_)

        return cqls

    '''执行cypher查询，并返回相应结果'''

    def search(self, cqls):
        final_answers = []
        for cql_ in cqls:
            question_type = cql_['question_type']
            queries = cql_['cql']
            answers = []
            for query in queries:
                result = self.g.run(query).data()
                answers += result
            final_answer = self.answer_template(question_type, answers)
            if final_answer:
                final_answers.append(final_answer)
        return final_answers

    '''根据对应的qustion_type，调用相应的回复模板'''

    def answer_template(self, question_type, answers):
        final_answer = []
        if not answers:
            return ''

        if question_type == 'movie_star':
            desc = answers[0]['m']['star']
            subject = answers[0]['m']['name']
            final_answer = '《{0}》电影的评分是{1}'.format(subject, desc)

        if question_type == 'movie_time':
            desc = answers[0]['m']['runTime']
            subject = answers[0]['m']['name']
            final_answer = '《{0}》电影的总时长是{1}'.format(subject, desc)

        if question_type == 'movie_show_start':
            date = answers[0]['m']['releaseTime']
            d2 = neotime.Date(date.year, date.month, date.day)
            datestr = d2.__str__()
            subject = answers[0]['m']['name']
            final_answer = '《{0}》的首映时间是{1}'.format(subject, datestr)

        if question_type == 'movie_actor':
            List = []
            for ans in answers:
                desc = ans['m']['name']
                List.append(desc)
            final_answer = '该电影的主演有：{0}'.format(List)

        if question_type == 'movie_director':
            desc = answers[0]['m']['name']
            final_answer = '导演是{0}'.format(desc)

        if question_type == 'movie_type':
            List = []
            for ans in answers:
                desc = ans['m']['name']
                List.append(desc)
            final_answer = '{0}'.format(List)

        if question_type == 'movie_toMovie':
            List = []
            for ans in answers:
                desc = ans['m']['name']
                if desc not in List:
                    List.append(desc)
            final_answer = '该系列电影有：{0}'.format(List)

        if question_type == 'type_movie':
            List = []
            for ans in answers:
                desc = ans['m']['name']
                List.append(desc)
            final_answer = '{0}类别的电影如下：{1}'.format('该', List)

        if question_type == 'actor_movie':
            List = []
            for ans in answers:
                desc = ans['m']['name']
                List.append(desc)
            final_answer = '{0}'.format(List)

        if question_type == 'director_movie':
            List = []
            for ans in answers:
                desc = ans['m']['name']
                List.append(desc)
            final_answer = '有以下作品：{0}'.format(List)

        if question_type == 'associate_person':
            try:
                List = []
                himself = answers[0]['m']['name']
                for ans in answers:
                    desc = ans['r']['name']
                    List.append(desc)
                final_answer = '与{0}合作过的演员有：{1}'.format(himself, List)
            except:
                print('不符合该模块的格式pass过滤掉')
                pass

        if question_type == 'associate_movie':
            List = []
            for ans in answers:
                desc = ans['n']['name']
                List.append(desc)
            final_answer = '共同出演的电影有：{0}'.format(List)

        if question_type == 'date_movie' or question_type == 'less_date_movie' or question_type == 'more_date_movie' or question_type == 'range_date_movie':
            List = []
            for ans in answers:
                desc = ans['m']['name']
                List.append(desc)
            final_answer = '符合上映日期的有以下作品：{0}'.format(List)

        if question_type == 'time_movie' or question_type == 'less_time_movie' or question_type == 'more_time_movie' or question_type == 'range_time_movie':
            List = []
            for ans in answers:
                desc = ans['movies']['name']
                List.append(desc)
            final_answer = '符合时长要求的电影如下:{0}'.format(List)

        if question_type == 'star_movie' or question_type == 'less_star_movie' or question_type == 'more_star_movie' or question_type == 'range_star_movie':
            List = []
            for ans in answers:
                desc = ans['movies']['name']
                List.append(desc)
            final_answer = '待查找评分的电影如下:{0}'.format(List)

        if question_type == '':
            List = []
            final_answer = ""
            for ans in answers:
                name = ans['m']['name']
                releaseTime = ans['m']['releaseTime']
                runTime = ans['m']['runTime']
                star = ans['m']['star']
                final_answer += '待查找的电影信息如下:{0}, 上映日期{1}, 时长{2}, 评分{3}\r\n'.format(name, releaseTime.__str__(), runTime, star)

        return str(final_answer)
